package com.wzp.util.lru;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LRUCache {
    private static RedisClinet redisClinet;
    private final int capacity;
    private final Map<Integer, Integer> cache;
    private final ConcurrentLinkedQueue<Integer> lruList;
    private final Map<Integer, Lock> locks;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.cache = new ConcurrentHashMap<>();
        this.lruList = new ConcurrentLinkedQueue<>();
        this.locks = new ConcurrentHashMap<>();
    }

    public int get(int key) {
        if (!cache.containsKey(key)) {
            Lock lock = locks.computeIfAbsent(key, k -> new ReentrantLock());
            lock.lock();
            try {
                // Double check if value has been cached by another thread
                if (!cache.containsKey(key)) {
//                    int result = redisClinet.get(key);
//                    if (result != 0) {
                        put(key, key);
//                    }
                    return key;
                }
            } finally {
                lock.unlock();
            }
            return -1;
        }
        lruList.remove(key);
        lruList.add(key);
        return cache.get(key);
    }

    public void put(int key, int value) {
        if (cache.containsKey(key)) {
            lruList.remove(key);
        } else if (cache.size() >= capacity) {
            int lruKey = lruList.poll();
            cache.remove(lruKey);
            locks.remove(lruKey);
        }
        lruList.add(key);
        cache.put(key, value);
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache(3);
        cache.put(1, 1);
        cache.put(2, 2);
        cache.put(3, 3);
        System.out.println(cache.get(1)); // 输出 1
        cache.put(4, 4);
        System.out.println(cache.get(2)); // 输出 -1，因为缓存容量为 3，之前的 key 2 被淘汰了
    }
}
